/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022.  All rights reserved.2023.
 */
package service

import (
	"errors"
	"fmt"
	"prim-server/common"
	"prim-server/config"
	"prim-server/dao"
	"prim-server/logger"
	"prim-server/model"
	"prim-server/util"
	"prim-server/util/toolcbc"
	"strings"
	"sync"
	"time"

	"github.com/spf13/cast"
)

const (
	defaultCurrency      = "CNY"
	defaultAmount        = 0.00
	defaultPaymentMethod = ""
)

const (
	//支持的operationType属性
	increaseAmount = 1
	reduceAmount   = 2

	//支持的operationType
	//充值--余额额度增加
	operationTypeOfCharge = 1

	//退款--余额/信用额度增加
	operationTypeOfRefund = 2

	//购买--余额/信用额度减少
	operationTypeOfPurchase = 3

	//管理员调整信用额度--信用额度增加
	operationTypeOfAjustCredit = 4

	//账户状态
	balanceStatusOfActive = true
	balanceStatusOfFrozen = false

	//调整云上额度操作
	adjustTypeOfIncrease = int32(1)
	adjustTypeOfReduce   = int32(2)
)

// 设置账户比较精度，只保留小数点后2位
const minAmount float64 = 0.01
const epsilon float64 = 1e-9

// 锁
var lock sync.Mutex

// 默认时间
var defaultTime time.Time = util.GetDefaultTime()

// 默认操作员
var defaultOperator string = config.GetConfig().AdminConfig.Name

// 支持的operationType及其对应的属性(增加或者减少)
var usedOpetationType map[int]int

func init() {
	//初始化支持的账户操作
	usedOpetationType = make(map[int]int)
	usedOpetationType[operationTypeOfCharge] = increaseAmount
	usedOpetationType[operationTypeOfRefund] = increaseAmount
	usedOpetationType[operationTypeOfPurchase] = reduceAmount
	usedOpetationType[operationTypeOfAjustCredit] = increaseAmount
}

// 判断是否为增加账户额度的操作
func IsOperationOfIncreaseAmount(operationType int) bool {
	value, ok := usedOpetationType[operationType]
	if ok {
		if value == increaseAmount {
			return true
		}
	}
	return false
}

// 判断是否为减少账户额度的操作
func IsOperationOfReduceAmount(operationType int) bool {
	value, ok := usedOpetationType[operationType]
	if ok {
		if value == reduceAmount {
			return true
		}
	}
	return false
}

// 账户状态是否为被冻结
func IsBalanceFrozen(balanceStatus bool) bool {
	return balanceStatus == balanceStatusOfFrozen
}

func CheckAmountZero(amount float64) bool {
	return !checkAmountNotZero(amount)
}

// 判断amount是否>= 0.01
func checkAmountNotZero(amount float64) bool {
	// == 0.01
	if util.Float64Equal(amount, minAmount, epsilon) {
		return true
	}
	// >0.01,即amount比0.01至少要多0.01才算更大,0.01为最小单位
	if amount > minAmount && isFloatValiad(amount) {
		return true
	}
	return false
}

// 最多两位小数
func isFloatValiad(f float64) bool {
	decimalStr := cast.ToString(f)
	//是否为负数
	if strings.Contains(decimalStr, "-") {
		return false
	}
	//是否为正整数
	if !strings.Contains(decimalStr, ".") {
		return true
	}
	parts := strings.Split(decimalStr, ".")
	if len(parts) != 2 {
		return false
	}
	return len(parts[1]) <= 2
}

// 判断expectedBigger是否大于expectedSmaller,最小单位为0.01
func checkAmountLarger(expectedBigger, expectedSmaller float64) bool {
	diff := expectedBigger - expectedSmaller
	return checkAmountNotZero(diff)
}

// 判断expectedBigger是否大于expectedSmaller,最小单位为0.01
func checkAmountLargerAndEqual(expectedBigger, expectedSmaller float64) bool {
	diff := expectedBigger - expectedSmaller
	if diff < epsilon || checkAmountNotZero(diff) {
		return true
	}
	return false
}

// 判断对余额账户和信用账户的操作是否有效
func validateOperationType(operationType int) bool {
	if _, ok := usedOpetationType[operationType]; ok {
		return true
	}
	return false
}

// 创建余额账户--已存在直接返回
func createBalanceAccount(userId, cloudUserId string) error {
	//error has been handled,return directly
	balanceAcount, err := GetBalanceAccountOneWithUserId(userId)
	if err != nil {
		return err
	}
	if balanceAcount != nil {
		return nil
	}
	balance := &model.Balance{
		UserId:        userId,
		CloudUserId:   cloudUserId,
		BalanceStatus: true,
		Currency:      defaultCurrency,
		Amount:        defaultAmount,
		DebtAmount:    defaultAmount,
	}
	err = dao.GetBalanceDao().SaveBalanceInfo(balance)
	if err != nil {
		logger.Error("create balance account error: %v, userId: %s", err.Error(), userId)
		return err
	}
	return nil
}

// 创建信用账户, 已存在直接返回
func createCreditAccount(userId, cloudUserId string) error {
	//error has been handled,return directly
	creditAcount, err := GetCreditAccountOneWithUserId(userId)
	if err != nil {
		return err
	}
	if creditAcount != nil {
		return nil
	}
	credit := &model.Credit{
		UserId:           userId,
		CloudUserId:      cloudUserId,
		CreditAmount:     defaultAmount,
		CreditDebtAmount: defaultAmount,
		Currency:         defaultCurrency,
		ExpireTime:       defaultTime,
	}
	err = dao.GetCreditDao().SaveCreditInfo(credit)
	if err != nil {
		logger.Error("create credit account error: %v, userId: %s", err.Error(), userId)
		return err
	}
	return nil
}

// 创建所有账户--余额账户和信用账户
func CreatedAccount(userId, cloudUserId string) error {
	err := createBalanceAccount(userId, cloudUserId)
	//error has been handled,return directly
	if err != nil {
		return err
	}
	err = createCreditAccount(userId, cloudUserId)
	//error has been handled,return directly
	if err != nil {
		return err
	}
	return nil
}

// 删除余额账户
func deleteBalanceAccount(userId string) error {
	//error has been handled,return directly
	balanceAcount, err := GetBalanceAccountOneWithUserId(userId)
	if err != nil {
		return err
	}
	if balanceAcount == nil {
		return errors.New("不存在余额账户，无需删除")
	}
	if !balanceAcount.BalanceStatus || checkAmountNotZero(balanceAcount.DebtAmount) {
		return errors.New("余额账户处于冻结或者欠费状态，无法删除")
	}
	if checkAmountNotZero(balanceAcount.Amount) {
		return errors.New("账户存在余额，无法删除")
	}
	err = dao.GetBalanceDao().DeleteBalanceInfo(userId)
	if err != nil {
		logger.Error("delete balance account error: %v, userId: %s", err.Error(), userId)
		return errors.New("删除余额账户失败")
	}
	return nil
}

// 删除信用账户
func deleteCreditAccount(userId string) error {
	//error has been handled,return directly
	creditAccount, err := GetCreditAccountOneWithUserId(userId)
	if err != nil {
		return err
	}
	if creditAccount == nil {
		return errors.New("不存在信用账户，无需删除")
	}
	if !creditAccount.CreditStatus || checkAmountNotZero(creditAccount.CreditDebtAmount) {
		return errors.New("信用账户处于冻结或者欠费状态，无法删除")
	}
	err = dao.GetCreditDao().DeleteCreditInfo(userId)
	if err != nil {
		logger.Error("delete credit account error: %v, userId: %s", err.Error(), userId)
		return errors.New("删除信用账户失败")
	}
	return nil
}

// 删除所有账户--余额账户和信用账户
func DeleteAccount(userId string) error {
	err := deleteBalanceAccount(userId)
	//error has been handled,return directly
	if err != nil {
		return err
	}
	err = deleteCreditAccount(userId)
	//error has been handled,return directly
	if err != nil {
		return err
	}
	return nil
}

// 查找余额账户
func GetBalanceAccountOneWithUserId(userId string) (*model.Balance, error) {
	balances, _, err := GetBalanceAccountAll([]string{userId}, nil, nil, nil)
	//error has been handled,return directly
	if err != nil {
		return nil, err
	}
	if balances == nil {
		return nil, nil
	}
	return balances[0], nil
}

func GetBalanceAccountAll(userId []string, balanceStatus []bool, page, pageSzie *int) ([]*model.Balance, int, error) {
	queryParameter := &common.QueryBalanceDetail{
		UserId:        userId,
		BalanceStatus: balanceStatus,
		Page:          page,
		PageSize:      pageSzie,
	}
	balanceAccounts, totalCount, err := dao.GetBalanceDao().GetBalanceInfo(queryParameter)
	if err != nil {
		logger.Error("get balance account error: %v, userId: %s,", err.Error(), fmt.Sprint(userId))
		return nil, 0, errors.New("查询余额账户失败")
	}
	//已处理不存在的情况
	if len(balanceAccounts) == 0 {
		return nil, 0, nil
	}
	return balanceAccounts, totalCount, nil
}

// 查找信用账户
func GetCreditAccountOneWithUserId(userId string) (*model.Credit, error) {
	credits, _, err := GetCreditAccountAll([]string{userId}, nil, nil, nil, nil, nil, nil)
	//error has been handled,return directly
	if err != nil {
		return nil, errors.New("查询信用账户失败")
	}
	if credits == nil {
		return nil, nil
	}
	return credits[0], nil
}

func GetCreditAccountAll(userId []string, creditStatus []bool,
	expireTimeBegin, expireTimeEnd *int64, page, pageSzie *int,
	currency *string) ([]*model.Credit, int, error) {
	queryParameter := &common.QueryCreditDetail{
		UserId:            userId,
		CreditStatus:      creditStatus,
		ExpireTimeBegin:   expireTimeBegin,
		ExpireTimeTimeEnd: expireTimeEnd,
		Page:              page,
		PageSize:          pageSzie,
		Currency:          currency,
	}
	creditAccounts, totalCount, err := dao.GetCreditDao().GetCreditInfo(queryParameter)
	if err != nil {
		logger.Error("get credit accountAll error: %v, userId: %s", err.Error(), fmt.Sprint(userId))
		return nil, 0, errors.New("查询余额账户失败")
	}
	if totalCount == 0 || len(creditAccounts) == 0 {
		return nil, 0, nil
	}
	return creditAccounts, totalCount, nil
}

// 更新余额账户
func UpdateBalanceAccount(userId, cloudUserId string, balanceStatus *bool,
	operationType int, amount *float64, paymentMethod string) error {
	balanceAccount, err := GetBalanceAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return errors.New("查询余额账户失败")
	}
	if balanceAccount == nil {
		return errors.New("未创建余额账户")
	}
	if !validateOperationType(operationType) {
		logger.Error("invalid operation type: %v", operationType)
		return errors.New("不支持的账户更新操作")
	}
	if balanceStatus != nil {
		balanceAccount.BalanceStatus = *balanceStatus
	}
	if amount != nil {
		if IsOperationOfIncreaseAmount(operationType) {
			if !(operationType == operationTypeOfCharge && util.ValidatePaymentMethod(paymentMethod)) {
				paymentMethod = defaultPaymentMethod
			}
			err = updateBalanceAccountForIncrease(userId, *amount, defaultOperator, operationType, paymentMethod)
			//error has been handled,return directly
			if err != nil {
				return err
			}
		}
		if IsOperationOfReduceAmount(operationType) {
			//error has been handled,return directly
			err = updateBalanceAccountForReduce(userId, cloudUserId, *amount, defaultOperator, operationType)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// 余额增加时发生的余额账户更新
// paymentMethod仅在充值时有效
// 余额增加的operationType: 1. 充值 2.退款
func updateBalanceAccountForIncrease(userId string, amount float64,
	operatorId string, operationType int, paymethod string) error {
	//退款/充值时增加余额
	balanceAccount, err := GetBalanceAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return errors.New("查询余额账户失败")
	}
	if balanceAccount == nil {
		return errors.New("未创建余额账户")
	}
	if CheckAmountZero(amount) {
		return errors.New("更新额度有误")
	}
	//更新余额账户:
	//1.如果有欠费，优先归还
	//2. 没有欠费时增加余额
	if checkAmountNotZero(balanceAccount.DebtAmount) {
		//如果增加的额度大于等于欠费，归还后欠款后余额增加
		balanceAccount.DebtAmount -= amount
		if checkAmountLargerAndEqual(amount, balanceAccount.DebtAmount) {
			balanceAccount.Amount += (amount - balanceAccount.DebtAmount)
		}
	} else {
		balanceAccount.Amount += amount
	}
	if checkAmountNotZero(balanceAccount.Amount) && IsBalanceFrozen(balanceAccount.BalanceStatus) {
		//如果充值之后余额>=0.01 且原账户处于冻结状态，则解冻账户
		balanceAccount.BalanceStatus = balanceStatusOfActive
	}
	err = dao.GetBalanceDao().UpdateBalanceInfo(balanceAccount)
	if err != nil {
		logger.Error("update balance account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新余额账户失败")
	}
	return nil
}

// 余额减少时的账户检查,成功返回balance对象
func CheckBalanceForReduce(userId string, amount float64) (*model.Balance, error) {
	//支付时需要减少金额
	//支付的条件：1.账户未冻结，2.账户没有欠费，3.账户有余额且余额大于等于支付所需要的额度
	balanceAccount, err := GetBalanceAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return nil, errors.New("查询余额账户失败")
	}
	if balanceAccount == nil {
		return nil, errors.New("未创建余额账户")
	}
	if CheckAmountZero(amount) {
		return nil, errors.New("更新额度有误")
	}
	if !balanceAccount.BalanceStatus {
		return nil, errors.New("账户冻结中")
	}
	if checkAmountNotZero(balanceAccount.DebtAmount) {
		return nil, errors.New("账户欠费中")
	}
	//消费金额大于账户余额
	if checkAmountLarger(amount, balanceAccount.Amount) {
		return nil, errors.New("账户余额不足")
	}
	return balanceAccount, nil
}

// 余额减少时发生的余额账户更新
// 余额减少的operationType: 1. 消费
func updateBalanceAccountForReduce(userId, cloudUserId string, amount float64,
	operatorId string, operationType int) error {
	//支付时需要减少金额
	//支付的条件：1.账户未冻结，2.账户没有欠费，3.账户有余额且余额大于等于支付所需要的额度
	balanceAccount, err := CheckBalanceForReduce(userId, amount)
	if err != nil {
		return err
	}
	//更新余额账户
	balanceAccount.Amount -= amount
	err = dao.GetBalanceDao().UpdateBalanceInfo(balanceAccount)
	if err != nil {
		logger.Error("update balance account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新余额账户失败")
	}
	//写入balanceRecord
	return nil
}

// 更新信用账户
func UpdateCreditAccount(userId, cloudUserId string, creditStatus *bool,
	operationType *int, amount *float64) error {
	creditAccount, err := GetCreditAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return errors.New("查询信用账户失败")
	}
	if creditAccount == nil {
		return errors.New("未创建信用账户")
	}
	if operationType != nil {
		if !validateOperationType(*operationType) {
			logger.Error("invalid operation type:%v", *operationType)
			return errors.New("不支持的账户更新操作")
		}
	}
	if creditStatus != nil {
		creditAccount.CreditStatus = *creditStatus
	}
	if amount != nil {
		if IsOperationOfIncreaseAmount(*operationType) {
			err = updateCreditAccountForIncrease(userId, cloudUserId, *amount, defaultOperator, *operationType)
			//error has been handled,return directly--直接返回
			if err != nil {
				return err
			}
		}
		if IsOperationOfReduceAmount(*operationType) {
			//error has been handled,return directly--直接返回
			err = updateCreditAccountForReduce(userId, cloudUserId, *amount, defaultOperator, *operationType)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// 更新信用账户
// 额度增加的operationType: 1. 管理员调整信用额度 2.退款
func updateCreditAccountForIncrease(userId, cloudUserId string, amount float64,
	operatorId string, operationType int) error {
	//退款/充值时增加余额
	creditAccount, err := GetCreditAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return errors.New("查询信用账户失败")
	}
	if creditAccount == nil {
		return errors.New("未创建信用账户")
	}
	if CheckAmountZero(amount) {
		return errors.New("调整的信用额度有误,至少为0.01")
	}
	//更新信用账户:
	//1.如果有欠费，优先归还额度
	//2. 没有欠费时增加额度
	if checkAmountNotZero(creditAccount.CreditDebtAmount) {
		//如果增加的额度大于等于欠费，归还后欠款后信用额度增加
		creditAccount.CreditDebtAmount -= amount
		if checkAmountLargerAndEqual(amount, creditAccount.CreditDebtAmount) {
			creditAccount.CreditAmount += (amount - creditAccount.CreditDebtAmount)
		}
	} else {
		creditAccount.CreditAmount += amount
	}
	//更新信用账户
	err = dao.GetCreditDao().UpdateCreditInfo(creditAccount)
	if err != nil {
		logger.Error("update credit account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新信用账户失败")
	}
	//写入balanceRecord
	creditRecord := &model.CreditRecord{
		CreditRecordId: util.GetUUID32(),
		UserId:         userId,
		CloudUserId:    cloudUserId,
		OperatorId:     operatorId,
		OperationType:  operationType,
		OperationTime:  util.GetUTC(time.Now()),
		Currency:       defaultCurrency,
		Amount:         amount,
		ExpireTime:     creditAccount.ExpireTime,
	}
	err = dao.GetCreditRecordDao().SaveCreditRecordInfo(creditRecord)
	if err != nil {
		logger.Error("update credit account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新信用额度变更记录失败")
	}
	return nil
}

// 更新信用账户--购买，额度减少
// 额度减少的operationType: 1. 消费
func updateCreditAccountForReduce(userId, cloudUserId string, amount float64,
	operatorId string, operationType int) error {
	//支付时需要减少金额
	//支付的条件：1.账户未冻结，2.账户没有欠费，3.账户有余额且余额大于等于支付所需要的额度
	creditAccount, err := GetCreditAccountOneWithUserId(userId)
	//err has been recorded, return immediately
	if err != nil {
		return errors.New("查询余额账户失败")
	}
	if creditAccount == nil {
		return errors.New("未创建信用账户")
	}
	if CheckAmountZero(amount) {
		return errors.New("更新额度有误")
	}
	if !creditAccount.CreditStatus {
		return errors.New("信用账户冻结中")
	}
	if checkAmountNotZero(creditAccount.CreditDebtAmount) {
		return errors.New("账户欠费中")
	}
	if checkAmountLarger(amount, creditAccount.CreditAmount) {
		return errors.New("信用账户余额不足")
	}
	//更新余额账户
	creditAccount.CreditAmount -= amount
	err = dao.GetCreditDao().UpdateCreditInfo(creditAccount)
	if err != nil {
		logger.Error("update credit account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新信用账户失败")
	}
	//写入balanceRecord
	creditRecord := &model.CreditRecord{
		CreditRecordId: util.GetUUID32(),
		UserId:         userId,
		CloudUserId:    cloudUserId,
		OperatorId:     operatorId,
		OperationType:  operationType,
		OperationTime:  util.GetUTC(time.Now()),
		Currency:       defaultCurrency,
		Amount:         amount,
	}
	err = dao.GetCreditRecordDao().SaveCreditRecordInfo(creditRecord)
	if err != nil {
		logger.Error("update credit account error: %v, userId: %s", err.Error(), userId)
		return errors.New("更新信用额度变更记录失败")
	}
	return nil
}

// 创建并保存余额调整记录
func CreateAndSaveDefaultBalianceRecordForCharge(userId, cloudUserId, paymentMethod string, paymentAmount float64) (*model.BalanceRecord, error) {
	balanceRecord, err := CreateAndSaveBalanceRecord(userId, cloudUserId, defaultOperator,
		operationTypeOfCharge, time.Now(), defaultCurrency, paymentAmount,
		paymentMethod, util.GetPaymentStatusOfPaying())
	//err has been recorded, return immediately
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}
	return balanceRecord, nil
}
func CreateAndSaveBalanceRecord(userId, cloudUserId, operatorId string,
	operationType int, operationTime time.Time,
	currency string, amount float64,
	paymentMethod, paymentStatus string) (*model.BalanceRecord, error) {
	balanceRecord := BuildBalanceRecord(userId, cloudUserId, operatorId, operationType, operationTime, currency, amount, paymentMethod, paymentStatus)
	//err has been recorded, return immediately
	err := dao.GetBalanceRecordDao().SaveBalanceRecordInfo(balanceRecord)
	if err != nil {
		logger.Error("CreateAndSaveBalanceRecord error: %v, userId: %s", err.Error(), userId)
		return nil, errors.New("创建余额调整记录失败")
	}
	return balanceRecord, nil
}

// 创建余额调整记录
func BuildBalanceRecord(userId, cloudUserId, operatorId string,
	operationType int, operationTime time.Time,
	currency string, amount float64,
	paymentMethod, paymentStatus string) *model.BalanceRecord {
	balanceRecord := &model.BalanceRecord{
		BalanceRecordId: util.GetUUID32(),
		UserId:          userId,
		CloudUserId:     cloudUserId,
		OperatorId:      operatorId,
		OperationType:   operationType,
		OperationTime:   util.GetUTC(operationTime),
		Currency:        defaultCurrency,
		Amount:          amount,
		PaymentMethod:   paymentMethod,
		PaymentStatus:   paymentStatus,
	}

	return balanceRecord
}

// 更新余额调整记录
func UpdateBalanceRecordPaymentStatus(balanaceRecordId string, paymentStatus string) error {
	lock.Lock()
	balanceRecord, err := GetBalanceRecordOneWithRecordId(balanaceRecordId)
	if err != nil {
		logger.Error(err.Error())
	}
	balanceRecord.PaymentStatus = paymentStatus
	err = dao.GetBalanceRecordDao().UpdateBalanceRecordInfo(balanceRecord)
	if err != nil {
		logger.Error(err.Error())
	}
	lock.Unlock()
	return nil

}

// 查找余额调整记录
func GetBalanceRecordOneWithRecordId(balanceRecordId string) (*model.BalanceRecord, error) {
	queryParameter := &common.QueryBalanceRecordDetail{
		BalanceRecordId: []string{balanceRecordId},
	}
	balanceRecords, totalCount, err := GetBalanceRecordAllWithParameter(queryParameter)
	//已处理不存在的情况
	if err != nil {
		logger.Error("get balance record error: %v, balanceRecordId: %s", err.Error(), balanceRecordId)
		return nil, errors.New("查询余额调整记录失败")
	}
	if totalCount == 0 {
		return nil, nil
	}
	return balanceRecords[0], nil
}
func GetBalanceRecordOneWithUserId(userId string) ([]*model.BalanceRecord, int, error) {
	queryParameter := &common.QueryBalanceRecordDetail{
		UserId: []string{userId},
	}
	balanceRecords, totalCount, err := GetBalanceRecordAllWithParameter(queryParameter)
	//已处理不存在的情况
	if err != nil {
		logger.Error("get balance record error: %v, userId: %s", err.Error(), userId)
		return nil, 0, errors.New("查询余额调整记录失败")
	}
	return balanceRecords, totalCount, nil
}
func GetBalanceRecordAll(balanceRecordId, userId []string, operatorType []int,
	operationTimeBegin, operationTimeEnd *int64,
	currency, paymentMethod *string, page, pageSize *int) ([]*model.BalanceRecord, int, error) {
	queryParameter := &common.QueryBalanceRecordDetail{
		BalanceRecordId:    balanceRecordId,
		UserId:             userId,
		OperationType:      operatorType,
		OperationTimeBegin: operationTimeBegin,
		OperationTimeEnd:   operationTimeEnd,
		Currency:           currency,
		PaymentMethod:      paymentMethod,
		Page:               page,
		PageSize:           pageSize,
	}
	return GetBalanceRecordAllWithParameter(queryParameter)
}
func GetBalanceRecordAllWithParameter(queryParameter *common.QueryBalanceRecordDetail) ([]*model.BalanceRecord, int, error) {
	if queryParameter == nil {
		return nil, 0, nil
	}
	balanceRecords, totalCount, err := dao.GetBalanceRecordDao().GetBalanceRecordInfo(queryParameter)
	if err != nil {
		logger.Error("get balance record error: %v", err.Error())
		return nil, 0, errors.New("查询余额账户调整记录失败")
	}
	return balanceRecords, totalCount, nil
}

// 查找信用额度调整记录
func GetCreditRecordOneWithUserId(userId string) (*model.CreditRecord, error) {
	queryParameter := &common.QueryCreditRecordDetail{
		UserId: []string{userId},
	}
	creditRecords, _, err := GetCreditRecordAllWithParameter(queryParameter)
	//已处理不存在的情况
	if err != nil {
		logger.Error("get balance record error: %v, userId: %s", err.Error(), userId)
		return nil, errors.New("查询信用额度调整记录失败")
	}
	return creditRecords[0], nil
}
func GetCreditRecordAllWithParameter(queryParameter *common.QueryCreditRecordDetail) ([]*model.CreditRecord, int, error) {
	creditRecords, totalCount, err := dao.GetCreditRecordDao().GetCreditRecordInfo(queryParameter)
	if err != nil {
		logger.Error("get credit record error: %v", err.Error())
		return nil, 0, errors.New("查询信用账户调整记录失败")
	}
	return creditRecords, totalCount, nil
}
func GetCreditRecordAll(creditRecordId, userId []string, operatorType []int,
	operationTimeBegin, operationTimeEnd, expireTimeBegin, expireTimeEnd *int64,
	currency *string, page, pageSize *int) ([]*model.CreditRecord, int, error) {
	queryParameter := &common.QueryCreditRecordDetail{
		CreditRecordId:     creditRecordId,
		UserId:             userId,
		OperationType:      operatorType,
		OperationTimeBegin: operationTimeBegin,
		OperationTimeEnd:   operationTimeEnd,
		Currency:           currency,
		ExpireTimeBegin:    expireTimeBegin,
		ExpireTimeEnd:      expireTimeEnd,
		Page:               page,
		PageSize:           pageSize,
	}
	return GetCreditRecordAllWithParameter(queryParameter)
}

// 更新余额账户和对应记录--充值完成
func UpdateAcountAndRecordForChargeCompleted(userId, cloudUserId string, amount *float64,
	paymentMethod, couponId string, balanceRecordId string) error {
	lastMount := *amount
	//如果有优惠券--根据优惠策略修改充值金额
	if len(couponId) != 0 {
		//do something to lastMount
		//TODO--coupon
	}
	err := UpdateBalanceAccount(userId, cloudUserId, nil, operationTypeOfAjustCredit, &lastMount, paymentMethod)
	if err != nil {
		logger.Error("update account and record error: %v, userId: %s", err.Error(), userId)
		return err
	}
	err = UpdateBalanceRecordPaymentStatus(balanceRecordId, util.GetPaymentStatusOfCompleted())
	if err != nil {
		logger.Error("update account and record error: %v, userId: %s", err.Error(), userId)
		return err
	}
	return nil
}

// 更新余额账户和对应记录--支付订单
func UpdateAcountAndRecordForPurCharse(userId, cloudUserId, couponId string, amount *float64) error {
	lastMount := *amount
	//如果有优惠券--根据优惠策略修改充值金额
	if len(couponId) != 0 {
		//do something to lastMount
		//TODO--coupon
	}
	//1.更新账户余额
	err := UpdateBalanceAccount(userId, cloudUserId, nil, operationTypeOfPurchase, &lastMount, "")
	if err != nil {
		logger.Error("update account and record error: %v, userId: %s", err.Error(), userId)
		return err
	}
	//2.减少云上账户额度
	err = AjudstCloudCreditForReduce(cloudUserId, *amount)
	if err != nil {
		logger.Error("update account and record error: %v, userId: %s", err.Error(), userId)
		return err
	}
	return nil
}

// 查询云上账户信用额度--仅转售
func GetCloudCreditCoupons(userId []string) ([]toolcbc.CreditCoupon, error) {
	cloudUsers, err := dao.GetCloudUserDao().GetCloudUserInfo(userId)
	if err != nil {
		logger.Error(err.Error())
		return nil, errors.New("查找用户出错")
	}
	// 查询数据库出错
	if cloudUsers == nil {
		return nil, errors.New("用户不存在")
	}
	cloudUserIds := []string{}
	for _, cloudUser := range cloudUsers {
		cloudUserIds = append(cloudUserIds, cloudUser.CloudId)
	}
	reponse, err := toolcbc.QueryCloudCreditCoupons(cloudUserIds)
	if err != nil {
		logger.Error("get cloud credit error: %v, userId: %s", err.Error(), fmt.Sprint(userId))
		return nil, errors.New("查询信用额度失败")
	}
	return *reponse.CreditCoupons, nil
}

// 调整云上账户信用额度--仅转售
func AjudstCloudCredit(cloudUserId string, adjustType int32, amount float64) error {
	_, err := toolcbc.AdjustCloudCreditCoupons(cloudUserId, adjustType, amount)
	if err != nil {
		logger.Error("ajudst cloud credit error: %v, cloudUserId: %s, adjustType: %d, amount: %v", err.Error(), cloudUserId, adjustType, amount)
		return errors.New("调整云上账户信用额度失败")
	}
	return nil
}
func AjudstCloudCreditForIncrease(cloudUserId string, amount float64) error {
	return AjudstCloudCredit(cloudUserId, adjustTypeOfIncrease, amount)
}
func AjudstCloudCreditForReduce(cloudUserId string, amount float64) error {
	return AjudstCloudCredit(cloudUserId, adjustTypeOfReduce, amount)
}
func QueryCloudCreditRecord(userId, cloudUserId string, offset, limit int32) (*toolcbc.QueryCloudCreditRecordResponse, error) {
	if limit <= 0 {
		limit = 10
	}
	reponse, err := toolcbc.QueryCloudCreditRecord(cloudUserId, &offset, &limit)
	if err != nil {
		logger.Error("query cloud credit record error: %v, userId: %s, offset: %d, limit: %d", err.Error(), offset, limit)
		return nil, errors.New("查询云上账户信用额度调整记录失败")
	}
	return reponse, nil
}

func BuildResponseForBalanceQuery(userId string) (*common.BalanceQueryResponse, error) {
	balanceAccount, err := GetBalanceAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return nil, err
	}
	if balanceAccount == nil {
		return nil, errors.New("未创建余额账户")
	}
	response := &common.BalanceQueryResponse{
		UserId:     balanceAccount.UserId,
		DebtAmount: balanceAccount.DebtAmount,
		Amount:     balanceAccount.Amount,
		Currency:   balanceAccount.Currency,
	}
	return response, nil
}

func buildQueryParameterForBalanceChangeRecordQuery(req *common.BalanceChangeRecordQueryRequest) *common.QueryBalanceRecordDetail {
	if req == nil {
		return nil
	}
	queryParameter := &common.QueryBalanceRecordDetail{
		UserId:             []string{req.UserId},
		OperationTimeBegin: req.OperationTimeBegin,
		OperationTimeEnd:   req.OperationTimeEnd,
		Page:               req.Page,
		PageSize:           req.PageSize,
		TimeReverseOrder:   req.TimeReverseOrder,
	}
	if req.OperationType != nil {
		queryParameter.OperationType = []int{*req.OperationType}
	}
	if req.BalanceRecordId != nil {
		queryParameter.BalanceRecordId = []string{*req.BalanceRecordId}
	}
	return queryParameter
}

func BuildResponseForBalanceChangeRecordQuery(req *common.BalanceChangeRecordQueryRequest) (*common.BalanceChangeRecordQueryResponse, error) {
	//error has been handled,return directly
	queryParameter := buildQueryParameterForBalanceChangeRecordQuery(req)

	balanceRecords, totalCount, err := GetBalanceRecordAllWithParameter(queryParameter)
	if err != nil {
		return nil, err
	}
	response := &common.BalanceChangeRecordQueryResponse{
		UserId:     req.UserId,
		Size:       len(balanceRecords),
		TotalCount: totalCount,
	}
	records := []common.BalanceChangreRecord{}
	for _, record := range balanceRecords {
		addRecord := common.BalanceChangreRecord{
			OperationType:   record.OperationType,
			OperationTime:   util.GetTimeString(record.OperationTime),
			BalanceRecordId: record.BalanceRecordId,
			Amount:          record.Amount,
			PaymentMethod:   record.PaymentMethod,
		}
		records = append(records, addRecord)
	}
	response.ChangeRecord = records
	return response, nil
}

func BuildResposneForCreditQuery(userId string) (*common.CreditQueryResponse, error) {
	creditAccount, err := GetCreditAccountOneWithUserId(userId)
	//error has been handled,return directly
	if err != nil {
		return nil, err
	}
	if creditAccount == nil {
		return nil, errors.New("未创建信用账户")
	}
	response := &common.CreditQueryResponse{
		UserId:     creditAccount.UserId,
		DebtAmount: creditAccount.CreditDebtAmount,
		Amount:     creditAccount.CreditAmount,
		Currency:   creditAccount.Currency,
		ExpireTime: util.GetTimeString(creditAccount.ExpireTime),
	}
	return response, nil
}
